package aor2.cpu.blockregisters;

import aor2.components.InstructionCode;
import aor2.components.Signal;

public enum InstructionSignal {
	MOV, SUB, OR, INC, DEC, NOT, ASR, BRN, BSR, BNZ, INT, RTI, RTS, INTE, INTD, TRPE, TRPD, JSRIND, JMPIND, UNKNOWN;

	private static InstructionSignal active = null;

	private Signal signal;

	public Signal getSignal() {
		return signal;
	}

	public boolean isActive() {
		return signal.isActive();
	}

	public void setActive(boolean active) {
		signal.setActive(active);
	}

	private InstructionSignal() {
		signal = new Signal(false);
	}

	static public void setActive() {
		// XXX check
		if (active != null) {
			active.setActive(false);
			active = null;
		}
		long ir0 = InstructionRegister.IR0.getState();
		int code;
		code = (int) (ir0 & InstructionCode.dvoadrmask);
		if (code != 0) {
			switch (code) {
			case (int) InstructionCode.MOV: {
				MOV.setActive(true);
				active = MOV;
				return;
			}
			case (int) InstructionCode.SUB: {
				SUB.setActive(true);
				active = SUB;
				return;
			}
			case (int) InstructionCode.OR: {
				OR.setActive(true);
				active = OR;
				return;
			}
			default: {
				UNKNOWN.setActive(true);
				active = UNKNOWN;
				return;
			}
			}
		}
		code = (int) (ir0 & InstructionCode.bezadrmask);
		if (code == 0) {
			code = (int) (ir0 & 0x7L);
			switch (code) {
			case (int) (InstructionCode.RTS): {
				RTS.setActive(true);
				active = RTS;
				return;
			}
			case (int) (InstructionCode.RTI): {
				RTI.setActive(true);
				active = RTI;
				return;
			}
			case (int) (InstructionCode.INTE): {
				INTE.setActive(true);
				active = INTE;
				return;
			}
			case (int) (InstructionCode.INTD): {
				INTD.setActive(true);
				active = INTD;
				return;
			}
			case (int) (InstructionCode.TRPE): {
				TRPE.setActive(true);
				active = TRPE;
				return;
			}
			case (int) (InstructionCode.TRPD): {
				TRPD.setActive(true);
				active = TRPD;
				return;
			}
			default: {
				UNKNOWN.setActive(true);
				active = UNKNOWN;
				return;
			}
			}
		}

		if ((code = (int) (ir0 & InstructionCode.jednoadrmask)) != 0) {
			switch (code) {
			case (int) (InstructionCode.INC): {
				INC.setActive(true);
				active = INC;
				return;
			}
			case (int) (InstructionCode.DEC): {
				DEC.setActive(true);
				active = DEC;
				return;
			}
			case (int) (InstructionCode.NOT): {
				NOT.setActive(true);
				active = NOT;
				return;
			}
			case (int) (InstructionCode.ASR): {
				ASR.setActive(true);
				active = ASR;
				return;
			}
			case (int) (InstructionCode.JSRIND): {
				JSRIND.setActive(true);
				active = JSRIND;
				return;
			}
			case (int) (InstructionCode.JMPIND): {
				JMPIND.setActive(true);
				active = JMPIND;
				return;
			}
			default: {
				code = (int) (ir0 & InstructionCode.skokmask);
				switch (code) {
				case (int) (InstructionCode.BNZ): {
					BNZ.setActive(true);
					active = BNZ;
					return;
				}
				case (int) (InstructionCode.BRN): {
					BRN.setActive(true);
					active = BRN;
					return;
				}
				case (int) (InstructionCode.BSR): {
					BSR.setActive(true);
					active = BSR;
					return;
				}
				default: {
					UNKNOWN.setActive(true);
					active = UNKNOWN;
					return;
				}
				}
			}
			}
		}
		UNKNOWN.setActive(true);
		active = UNKNOWN;

	}

	static public InstructionSignal getActive() {
		return active;
	}

	static public String info() {
		if (active == null)
			return "operation signal: not active";
		return "operation signal: " + active.name();
	}
}
